﻿using Ly.EBussiness.EntityFrameworkCore.Auth.User;
using Ly.EBussiness.EntityFrameworkCore.BaseEntity;
using Ly.EBussiness.EntityFrameworkCore.Entity;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;

namespace Ly.EBussiness.EntityFrameworkCore;

public partial class EBussinessDbContext
{
    private readonly ICurrentUser _currentUser;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="options"></param>
    /// <param name="currentUser"></param>
    public EBussinessDbContext(DbContextOptions<EBussinessDbContext> options,
        ICurrentUser currentUser) : base(options)
    {
        _currentUser = currentUser;
    }

    public static string GenerateUniqueSeed()
    {
        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
        var random = new Random();
        var randomPart = random.Next(100000, 999999); // 生成一个五位的随机数
        // 将时间戳截取后6位与随机数拼接，确保唯一性
        var seed = $"{timestamp % 1000000:000000}{randomPart:000000}";
        return string.Concat("1",
            int.Parse(DateTime.Now.Year.ToString().AsSpan(1)).ToString(),
            int.Parse(DateTime.Now.Month.ToString().AsSpan()).ToString(),
            int.Parse(DateTime.Now.Day.ToString().AsSpan()).ToString(), seed[..6]);
    }

    private string getUserId()
    {
        return _currentUser?.Id ??　"666";
    }

    /// <summary>
    /// </summary>
    /// <param name="entry">
    /// </param>
    protected override void SetCreationAuditProperties(EntityEntry entry)
    {
        base.SetCreationAuditProperties(entry);
        if (entry.Entity is BaseAuditEntity<int> modifyEntity)
        {
            modifyEntity.LastModificationTime = DateTime.Now;
            modifyEntity.CreationTime = DateTime.Now;
            modifyEntity.CreatorId = getUserId();
            modifyEntity.LastModifierId = getUserId();
        }
    }

    protected override void SetModificationAuditProperties(EntityEntry entry)
    {
        base.SetModificationAuditProperties(entry);
        if (entry.Entity is BaseAuditEntity<int> modifyEntity)
        {
            modifyEntity.LastModificationTime = DateTime.Now;
            modifyEntity.LastModifierId = getUserId();
        }
    }

    /// <summary>
    /// </summary>
    /// <param name="entry">
    /// </param>
    protected override void SetDeletionAuditProperties(EntityEntry entry)
    {
        base.SetDeletionAuditProperties(entry);

        if (entry.Entity is BaseAuditEntity<int> modifyEntity)
        {
            modifyEntity.DeleterId = getUserId();
        }
    }

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
    {
        //添加操作
        ChangeTracker.Entries()
            .Where(e => e is { State: EntityState.Added, Entity: BaseAuditEntity<int> modifyEntity }).ToList()
            .ForEach(e =>
            {
                if (e.Entity is OrderInfo o)
                {
                    o.OrderId = "O" + GenerateUniqueSeed();
                }

                var baseAuditEntity = ((BaseAuditEntity<int>)e.Entity);
                baseAuditEntity.CreationTime = DateTime.Now;
                baseAuditEntity.CreatorId = getUserId();
                baseAuditEntity.LastModificationTime = DateTime.Now;
                baseAuditEntity.LastModifierId = getUserId();
                baseAuditEntity.IsDeleted = false;
            });
        //修改操作
        ChangeTracker.Entries()
            .Where(e => e is { State: EntityState.Modified, Entity: BaseAuditEntity<int> modifyEntity }).ToList()
            .ForEach(e =>
            {
                var baseAuditEntity = ((BaseAuditEntity<int>)e.Entity);
                baseAuditEntity.LastModificationTime = DateTime.Now;
                baseAuditEntity.LastModifierId = getUserId();
                if (e.Entity is IEBussinessSoftDelete && baseAuditEntity.IsDeleted)
                {
                    baseAuditEntity.DeletionTime = DateTime.Now;
                    baseAuditEntity.DeleterId = getUserId();
                }
            });

        ChangeTracker.Entries()
            .Where(e => e is { State: EntityState.Deleted, Entity: BaseAuditEntity<int> modifyEntity }).ToList()
            .ForEach(e =>
            {
                var baseAuditEntity = ((BaseAuditEntity<int>)e.Entity);
                baseAuditEntity.DeletionTime = DateTime.Now;
                baseAuditEntity.DeleterId = getUserId();
            });
        return await base.SaveChangesAsync(cancellationToken);
    }
}